﻿// JCfg.cpp : 定义 DLL 的导出函数。
//

#include "pch.h"
#include "framework.h"
#include "JgConfig.h"
#include <iostream>
#include <fstream> 
#include <iomanip>              // std::setw()
#include "nlohmann_json/json.hpp"

#pragma execution_character_set("utf-8")
using json = nlohmann::json;


//Globle 
json jsonData;
wchar_t filename[4097];


// 判断文件是否存在
bool FileExists(LPCWSTR file_name)
{
	WIN32_FILE_ATTRIBUTE_DATA attrs = { 0 };
	return 0 != ::GetFileAttributesEx(file_name, ::GetFileExInfoStandard, &attrs);
}

bool a =FileExists(_T("e"));


//==================================================================================
//=====  导出变量  =================================================================
// 这是导出变量的一个示例
JCFG_API int nJCfg=1;

//==================================================================================
//=====  导出函数  =================================================================
// 这是导出函数的一个示例。
JCFG_API std::string Version(void)
{
	std::string s= "JgConfig v0.15 By JgAi " __DATE__ " "  __TIME__;
    return s;
}

//==================================================================================
//=====  导出类  ===================================================================
// 这是已导出类的构造函数。
CJgConfig::CJgConfig()
{
	setFilename (L"defaultConfig.json");
    return;
}
CJgConfig::~CJgConfig()
{
	saveCfg();
	return;
}


bool CJgConfig::setDefaultJson(const std::string&  jsonStr)
{
	jsonData =json::parse(jsonStr);
	return true;
}
bool CJgConfig::loadCfg()
{
	if (FileExists(filename))
	{
		std::ifstream fin(filename);
		fin >> jsonData;
		fin.close();
	}
	else
	{

	}
	return true;
}

bool CJgConfig::saveCfg()
{
	if (!FileExists(filename))
	{
		//return false;
	}
	std::ofstream fout(filename);
	fout << std::setw(4) <<  jsonData << std::endl;
	return true;
}
void CJgConfig::setFilename(LPCWSTR fn)
{
	wcscpy_s( filename ,4000,fn);
}
LPCWSTR CJgConfig::getFilename()
{
	return filename;
}

#ifndef _GROUP_JCFG_SET_asdfasdfasdfasdfqwer
//
//void CJgConfig::setInt(const std::string& key, int v) { jsonData[key] = v; }
//void CJgConfig::setBool(const std::string& key, bool v) { jsonData[key] = v; }
//void CJgConfig::setDouble(const std::string& key, double v) { jsonData[key] = v; }
//void CJgConfig::setString(const std::string& key, const std::string& v) { jsonData[key] = v; }
//void CJgConfig::setVectorInt(const std::string& key, const std::vector<int>& v) { jsonData[key] = v; }
//void CJgConfig::setVectorBool(const std::string& key, const std::vector<bool>& v) { jsonData[key] = v; }
//void CJgConfig::setVectorDouble(const std::string& key, const std::vector<double>& v) { jsonData[key] = v; }
//void CJgConfig::setVectorString(const std::string& key, const std::vector<std::string>& v) { jsonData[key] = v; }
//

// 注，key支持的长度最大为5. 即最多嵌套5层JSON对象
#define SETV(v)   size_t n = key.size();\
	 (n == 0)?jsonData[""] = v: \
	 (n == 1)?jsonData[key[0]] = v: \
	 (n == 2)?jsonData[key[0]][key[1]] = v: \
	 (n == 3)?jsonData[key[0]][key[1]][key[2]] = v: \
	 (n == 4)?jsonData[key[0]][key[1]][key[2]][key[3]] = v: \
	          jsonData[key[0]][key[1]][key[2]][key[3]][key[4]] = v;

void CJgConfig::setInt(const std::vector<std::string>& key, int v){ SETV(v); }
void CJgConfig::setBool(const std::vector<std::string>& key, bool v) { SETV(v); }
void CJgConfig::setDouble(const std::vector<std::string>& key, double v) { SETV(v); }
void CJgConfig::setString(const std::vector<std::string>& key, const std::string& v) { SETV(v); }
void CJgConfig::setVectorInt(const std::vector<std::string>& key, const std::vector<int>& v) { SETV(v); }
void CJgConfig::setVectorBool(const std::vector<std::string>& key, const std::vector<bool>& v) { SETV(v); }
void CJgConfig::setVectorDouble(const std::vector<std::string>& key, const std::vector<double>& v) { SETV(v); }
void CJgConfig::setVectorString(const std::vector<std::string>& key, const std::vector<std::string>& v) { SETV(v); }


#endif


#ifndef _GROUP_JCFG_GET_TTTTTTTTTTTTTTTTTTTTTTTo
//
//int    CJgConfig::getInt(const std::string& key, int vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//bool   CJgConfig::getBool(const std::string& key, bool vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//double CJgConfig::getDouble(const std::string& key, double vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//std::string CJgConfig::getString(const std::string& key, const std::string& vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//std::vector<int> CJgConfig::getVectorInt(const std::string& key, const std::vector<int>& vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//std::vector<bool> CJgConfig::getVectorBool(const std::string& key, const std::vector<bool>& vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//std::vector<double> CJgConfig::getVectorDouble(const std::string& key, const std::vector<double>& vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//std::vector<std::string> CJgConfig::getVectorString(const std::string& key, const std::vector<std::string>& vDef) { if (jsonData.contains(key)) return jsonData[key]; else return vDef; }
//

#define GETV(vDef)   size_t i,n = key.size();json t=jsonData;\
	if(n == 0)  if(t.contains("")) return t[""]; else return vDef; \
	for (i = 0; i < n; i++) \
	{ \
		if (!t.contains(key[i]))return vDef; \
		t = t[key[i]]; \
	} \
	return t; \

int    CJgConfig::getInt(const std::vector<std::string>& key, int vDef){ GETV(vDef) }
bool   CJgConfig::getBool(const std::vector<std::string>& key, bool vDef) { GETV(vDef) }
double CJgConfig::getDouble(const std::vector<std::string>& key, double vDef) { GETV(vDef) }
std::string CJgConfig::getString(const std::vector<std::string>& key, const std::string& vDef) { GETV(vDef) }
std::vector<int> CJgConfig::getVectorInt(const std::vector<std::string>& key, const std::vector<int>& vDef) { GETV(vDef) }
std::vector<bool> CJgConfig::getVectorBool(const std::vector<std::string>& key, const std::vector<bool>& vDef) { GETV(vDef) }
std::vector<double> CJgConfig::getVectorDouble(const std::vector<std::string>& key, const std::vector<double>& vDef) { GETV(vDef) }
std::vector<std::string> CJgConfig::getVectorString(const std::vector<std::string>& key, const std::vector<std::string>& vDef){ GETV(vDef) }

#endif